/*
 * Copyright 2005-2008 Pulse Technologies. Tutti i diritti riservati.
 */
package org.obsidianrad.server.services.obj2db.commodities;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.obsidianrad.server.services.obj2db.hessian.CriteriaHessian;
import org.obsidianrad.server.services.obj2db.hessian.CriteriaHessianMap;
import org.obsidianrad.server.services.obj2db.hessian.FiltererHessian;

/**
 * 
 * @author Eligio Colutta
 * @version $Rev: 4 $
 * @lastautorcommit $Author: eliosh $
 * @lastdatecommit $Date: 2009-10-31 12:37:28 +0100(sab, 31 ott 2009) $
 */
public class Filterer implements Serializable {

	private static final long serialVersionUID = -6140844522034551964L;
	
	protected String orderByClause;
	protected List<Criteria> oredCriteria;
	private String typeObject;
	
	@Deprecated
	public Filterer() {
		oredCriteria = new ArrayList<Criteria>();
	}

	public Filterer(String base){
		this.typeObject = base;
		oredCriteria = new ArrayList<Criteria>();
	}
	
	protected Filterer(Filterer example) {
		this.orderByClause = example.orderByClause;
		this.oredCriteria = example.oredCriteria;
	}

	public void setOrderByClause(String orderByClause) {
		this.orderByClause = orderByClause;
	}

	public String getOrderByClause() {
		return orderByClause;
	}

	public List<Criteria> getOredCriteria() {
		return oredCriteria;
	}

	public void or(Criteria criteria) {
		oredCriteria.add(criteria);
	}

	public Criteria createCriteria() {
		Criteria criteria = createCriteriaInternal();
		if (oredCriteria.size() == 0) {
			oredCriteria.add(criteria);
		}
		return criteria;
	}

	protected Criteria createCriteriaInternal() {
		Criteria criteria = new Criteria();
		return criteria;
	}

	public void clear() {
		oredCriteria.clear();
	}

	public String getTypeObject() {
		return typeObject;
	}

	public void setTypeObject(String typeObject) {
		this.typeObject = typeObject;
	}

	public void convertFromHessian(FiltererHessian filtererHessian){
		// TODO convert from hessian filterer to real filterer
		CriteriaHessian[] criteria = filtererHessian.getCriteria();
		for(int k=0; k<criteria.length; k++){
			if(criteria[k]!=null){
				Criteria crit = convertFromHessian(criteria[k]);
				this.or(crit);				
			}
		}
	}

	private static Criteria convertFromHessian(CriteriaHessian criteriaHessian){
		CriteriaHessianMap[] criteriaMap = criteriaHessian.getCriteriaMap();
		Criteria newCrit = new Criteria();
		for(int k=0; k<criteriaMap.length; k++){
			CriteriaHessianMap chm = criteriaMap[k];
			if(chm!=null){
				if(chm.getObjList()!=null){
					List<Object> values = Arrays.asList(chm.getObjList());
					newCrit.addCriterion(chm.getCondition(), values, chm.getProperty());
				}else if(chm.getObj2() != null){
					newCrit.addCriterion(chm.getCondition(), chm.getObj1(), chm.getObj2(), chm.getProperty());
				} else if(chm.getObj1()!=null){
					newCrit.addCriterion(chm.getCondition(), chm.getObj1(), chm.getProperty());
				}else{
					newCrit.addCriterion(chm.getCondition());
				}
			}
		}
		return newCrit;
	}
	
	
	public static class Criteria implements Serializable {

		private static final long serialVersionUID = -7965301561767075256L;

		protected List<String> criteriaWithoutValue;

		protected List<Map<String, Object>>  criteriaWithSingleValue;

		protected List<Map<String, Object>> criteriaWithListValue;

		protected List<Map<String, Object>> criteriaWithBetweenValue;

		public Criteria() {
			super();
			criteriaWithoutValue = new ArrayList<String>();
			criteriaWithSingleValue = new ArrayList<Map<String, Object>>();
			criteriaWithListValue = new ArrayList<Map<String, Object>>();
			criteriaWithBetweenValue = new ArrayList<Map<String, Object>>();
		}

		public boolean isValid() {
			return criteriaWithoutValue.size() > 0 || criteriaWithSingleValue.size() > 0 || criteriaWithListValue.size() > 0 || criteriaWithBetweenValue.size() > 0;
		}

		public List<String> getCriteriaWithoutValue() {
			return criteriaWithoutValue;
		}

		public List<Map<String, Object>>  getCriteriaWithSingleValue() {
			return criteriaWithSingleValue;
		}

		public List<Map<String, Object>> getCriteriaWithListValue() {
			return criteriaWithListValue;
		}

		public List<Map<String, Object>> getCriteriaWithBetweenValue() {
			return criteriaWithBetweenValue;
		}

		protected void addCriterion(String condition) {
			if (condition != null) {
				// throw new RuntimeException("Value for condition cannot be null");
				criteriaWithoutValue.add(condition);
			}
		}

		protected void addCriterion(String condition, Object value, String property) {
			if (value != null) {
				// throw new RuntimeException("Value for " + property + " cannot be null");
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("condition", condition);
				map.put("value", value);
				criteriaWithSingleValue.add(map);
			}
		}

		protected void addCriterion(String condition, List<Object> values, String property) {
			if (values != null && values.size() == 0) {
				// throw new RuntimeException("Value list for " + property + " cannot be null or empty");
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("condition", condition);
				map.put("values", values);
				criteriaWithListValue.add(map);
			}
		}

		protected void addCriterion(String condition, Object value1, Object value2, String property) {
			if (! (value1 == null || value2 == null) ){
				// throw new RuntimeException("Between values for " + property + " cannot be null");
				List<Object> list = new ArrayList<Object>();
				list.add(value1);
				list.add(value2);
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("condition", condition);
				map.put("values", list);
				criteriaWithBetweenValue.add(map);
			}
		}

		public void addLessOrEqualFilter(String field, Object value) {
			addCriterion(field + " <=", value, field);
		}

		public void addLessFilter(String field, Object value) {
			addCriterion(field + " <", value, field);
		}

		public void addGreaterFilter(String field, Object value) {
			addCriterion(field + " >", value, field);
		}

		public void addGreaterOrEqualFilter(String field, Object value) {
			addCriterion(field + " >=", value, field);
		}

		public void addEqualFilter(String field, Object value) {
			addCriterion(field + " =", value, field);
		}

		public void addNotEqualFilter(String field, Object value) {
			addCriterion(field + " <>", value, field);
		}

		public void addLikeFilter(String field, Object value) {
			addCriterion(field + " like", value, field);
		}
		
		public void addNotLikeFilter(String field, Object value) {
			addCriterion(field + " not like", value, field);
		}
		
		public void addBetweenFilter(String field, Object valueMin, Object valueMax) {
			addCriterion(field + " BETWEEN", valueMin, valueMax, field);
		}

		public void addNotBetweenFilter(String field, Object valueMin, Object valueMax) {
			addCriterion(field + " NOT BETWEEN", valueMin, valueMax, field);
		}

		public void addIsNull(String field) {
			addCriterion(field + " is null");
		}

		public void addIsNotNull(String field) {
			addCriterion(field + " is not null");
		}

		public void addInList(String field, List<Object> values){
			addCriterion(field + " in", values, field);
		}
		
		public void addNotInList(String field, List<Object> values){
			addCriterion(field + " not in", values, field);
		}
		
	}

}
